const
  csTranscodingInputFile = '-i "<INPUT FILE>"';
  csFFMpegVideoParams = ' -f %s -vcodec %s %s%s -copyts -pix_fmt yuv420p';
  csFFMpegAudioParams = ' -acodec %s -ab %d -ar 48000';

function GetAudioCodec(const aAudioCodec: string): string;
begin
  if (aAudioCodec = '') or SameText(aAudioCodec, 'AC3') then
    Result := 'ac3'
  else if SameText(aAudioCodec, 'AAC') then
    Result := 'libfaac'
  else if SameText(aAudioCodec, 'MP3') then
    Result := 'libmp3lame'
  else if SameText(aAudioCodec, 'MP2') then
    Result := 'mp2'
  else if SameText(aAudioCodec, 'WMA') then
    Result := 'wmav2'    
  else if SameText(aAudioCodec, 'DTS') then
    Result := 'dca'    
  else if SameText(aAudioCodec, 'LPCM') then  
    Result := 'pcm_s16be' 
  else
    Result := aAudioCodec
end;

function SameAudioCodec(const aAudioCodec: string; aCodecID: Integer): Boolean;
begin
  if (aAudioCodec = '') or SameText(aAudioCodec, 'AC3') then
    Result := aCodecID = CODEC_ID_AC3
  else if SameText(aAudioCodec, 'AAC') then
    Result := aCodecID = CODEC_ID_AAC
  else if SameText(aAudioCodec, 'MP3') then
    Result := aCodecID = CODEC_ID_MP3
  else if SameText(aAudioCodec, 'MP2') then
    Result := aCodecID = CODEC_ID_MP2
  else if SameText(aAudioCodec, 'WMA') then
    Result := aCodecID = CODEC_ID_WMAV2
  else
    Result := False
end;

function GetFileFormat(const aFileFormat: string): string;
begin
  if (aFileFormat = '') or SameText(aFileFormat, 'MPEG (DVD)') then
    Result := 'dvd'
  else if Pos('MPEGTS', aFileFormat) > 0 then
    Result := 'mpegts'
  else if Pos('ASF', aFileFormat) > 0 then
    Result := 'asf'
  else if SameText(aFileFormat, 'MP4') then
    Result := 'ipod'
  else if SameText(aFileFormat, 'MPEG1') then
    Result := 'mpeg'
  else
    Result := aFileFormat
end;

function GetVideoCodec(const aVideoCodec: string): string;
begin
  if (aVideoCodec = '') or SameText(aVideoCodec, 'MPEG2') then
    Result := 'mpeg2video'
  else if SameText(aVideoCodec, 'MPEG1') then
    Result := 'mpeg1video'
  else if SameText(aVideoCodec, 'WMV') then
    Result := 'wmv2'
  else if SameText(aVideoCodec, 'MPEG4') then
    Result := 'mpeg4'
  else if SameText(aVideoCodec, 'X264') then
    Result := 'libx264 -x264opts "fast-pskip=1:rc-lookahead=0:aq_mode=0" -partitions none -sc_threshold 0 -trellis 0 -me_method dia -refs 1 -subq 0 -vprofile baseline -level 30 -bufsize 10000000 '
  else
    Result := aVideoCodec
end;

function GetMultiThreadSupported(const aVideoCodec: string): Boolean;
begin
  Result := not MatchText(aVideoCodec, ['WMV', 'MPEG1', 'FLV'])
end;

function GetAudioBitrate(const aAudioCodec: string; aAudioBitrate: Integer): Integer;
begin
  if MatchText(aAudioCodec, ['MP2', 'MP3']) and (aAudioBitrate > 320000) then
    Result := 320000
  else
    Result := aAudioBitrate
end;

function GetAudioChannels(const aAudioCodec: string; aConfigAudioChannels, aStreamAudioChannels: Integer): Integer;
begin
  if aConfigAudioChannels > 0 then
    Result := aConfigAudioChannels
  else
    Result := aStreamAudioChannels;
  if (Result > 2) and MatchText(aAudioCodec, ['MP2', 'MP3']) then
    Result := 2
  else if (Result = 1) and MatchText(aAudioCodec, ['AAC', 'AC3']) then
    Result := 2
  else if Result > 6 then
    Result := 6
end;

procedure AddFilterParams(var aFilterParams: string; const aAddParams: string);
begin
  if aFilterParams <> '' then
    aFilterParams := aFilterParams + ',';
  aFilterParams := aFilterParams + aAddParams
end;
  
var
  iAudioStreamNo, iChannels, iCodecID, iFrameWidth, iFrameHeight, 
  iWidth, iHeight, iPadLeft, iPadTop, iPadRight, iPadBottom: Integer;
  sFrameRate, sParams, sVideoBitrate, sVideoMinMaxRate, sFilterParams, sPadParams: string;
begin
  sVideoMinMaxRate := '';
  if cfgTranscodingVideoBitrate > 0 then begin  
    sVideoBitrate := '-b:v ' + IntToStr(cfgTranscodingVideoBitrate);
    if cfgTranscodingVideoMinMaxRate then
      sVideoMinMaxRate := Format(' -minrate %d -maxrate %d -bufsize %d',
                  [cfgTranscodingVideoBitrate, cfgTranscodingVideoBitrate, 
                   WmsTranscodingBufferSize(cfgTranscodingVideoBitrate)])
  end else
    sVideoBitrate := '-sameq';      

  if mpInternetItem then
    TranscodingParams := WmsTranscodingProfileParams('Internet-television')
  else if mpSubItemsCount > 0 then 
    TranscodingParams := WmsTranscodingProfileParams('Movies (DVD)')
  else begin    
    sParams := WmsTranscodingInputParams;
    sParams := sParams + Format(csFFMPegVideoParams, [GetFileFormat(cfgTranscodingFileFormat),
           GetVideoCodec(cfgTranscodingVideoCodec), sVideoBitrate, sVideoMinMaxRate]);
    iAudioStreamNo := mpAudioStreamNo;
    if iAudioStreamNo <> -1 then begin
      iCodecID := WmsGetStreamCodecID('A', iAudioStreamNo);
      iChannels := WmsGetStreamChannels(iAudioStreamNo);
    end else begin
      iCodecID := CODEC_ID_NONE;
      iChannels := 0;
    end;
    if (iCodecID = CODEC_ID_NONE) and SameText(mpAudioCodec, 'AC3') then
      iCodecID := CODEC_ID_AC3;
    if cfgTranscodingAudioCopyAC3 and SameAudioCodec(cfgTranscodingAudioCodec, iCodecID) then
      sParams := sParams + ' -acodec copy'
    else begin
      sParams := sParams + Format(csFFMpegAudioParams, 
          [GetAudioCodec(cfgTranscodingAudioCodec), 
           GetAudioBitrate(cfgTranscodingAudioCodec, cfgTranscodingAudioBitrate)]);
      iChannels := GetAudioChannels(cfgTranscodingAudioCodec, cfgTranscodingAudioChannels, iChannels);
      if iChannels > 0 then
        sParams := sParams + ' -ac ' + IntToStr(iChannels)
    end;                                   
    sFrameRate := WmsGetVideoSettings(vstFrameRate);
    if sFrameRate = '' then    
      sFrameRate := cfgTranscodingFrameRate;
    if (mpFrameRate > 0) and (mpFrameRate < 25) then
      sFrameRate := '23.976';
    if (sFrameRate = '') then
      sFrameRate := '25';
    if sFrameRate <> '' then
      sParams := sParams + ' -r ' + sFrameRate;
    iWidth := mpWidth; iHeight := mpHeight;  
    if (iWidth > 0) and (iHeight > 0) then begin   
      sFilterParams := ''; sPadParams := '';    
      if WmsTranscodingFrameParams(iWidth, iHeight, cfgTranscodingScreenFormat,
                         iPadLeft, iPadTop, iPadRight, iPadBottom) then begin                         
        if mp3DVideoType in [1, 2] then begin
          iWidth  := iWidth  + iPadLeft + iPadRight;
          iHeight := iHeight + iPadTop + iPadBottom;                 
          if mp3DVideoType = 1 then
            iWidth  := (iWidth div 4) * 4
          else
            iHeight := (iHeight div 4) * 4          
        end;
        iFrameWidth  := iWidth;
        iFrameHeight := iHeight;
        if (mp3DVideoType = 0) and ((iPadLeft > 0) or (iPadRight > 0) or (iPadTop > 0) or (iPadBottom > 0)) then begin        
          Inc(iFrameWidth,  iPadLeft + iPadRight);
          Inc(iFrameHeight, iPadTop + iPadBottom);
          sPadParams := Format('pad=%d:%d:%d:%d:0x%s',
                        [iFrameWidth, iFrameHeight, iPadLeft, iPadTop, WmsConvertColor(cfgTranscodingPadColor)]);
          if cfgTranscodingFrameExists then
            sParams := sParams + cfgTranscodingFrameParams;
        end
      end else begin
        iFrameWidth  := iWidth;
        iFrameHeight := iHeight;
      end;
      AddFilterParams(sFilterParams, Format('scale=%d:%d', [iWidth, iHeight]));
      if sPadParams <> '' then AddFilterParams(sFilterParams, sPadParams);
      AddFilterParams(sFilterParams, 'setdar=' + cfgTranscodingAspectRatio);
      sParams := sParams + Format(' -vf "%s"', [sFilterParams]);
      sParams := sParams + WmsTranscodingSubTitleParams(
         iFrameWidth, iFrameHeight, iWidth, iHeight, iPadLeft, iPadTop);
      sParams := sParams + WmsTranscodingMapParams(iAudioStreamNo);
      if (cfgTranscodingThreadCount > 1) and GetMultiThreadSupported(cfgTranscodingVideoCodec) then
        sParams := sParams + ' -threads ' + IntToStr(cfgTranscodingThreadCount);
    end;
    TranscodingParams := sParams
  end  
end.